package com.lute.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;

import org.springframework.security.oauth2.common.json.JSONException;
import org.springframework.security.oauth2.common.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.lute.model.Admin;
import com.lute.model.Approver;
import com.lute.model.Client;
import com.lute.model.ClientAccountingPeriod;
import com.lute.model.ClientAdminProfile;
import com.lute.model.ClientProfile;
import com.lute.model.Employee;
import com.lute.model.EmployeeAccountingPeriod;
import com.lute.model.EmployeeProfile;
import com.lute.model.Role;
import com.lute.model.User;
import com.lute.model.UserEntitlement;
import com.lute.utils.ServerErrorResponse;

@Controller
public class FindEmployeesServlet {
	
	@RequestMapping (value="/findUsers",method= RequestMethod.POST, headers = "Content-type=application/json")
	public @ResponseBody String findEmployees(@RequestBody String dataJSON, HttpServletRequest request) throws JSONException {
		String result = "";
		JSONObject jsonReq;
		JSONObject jsonRes = new JSONObject();
		
		HttpSession session = request.getSession(false);
		if(session == null) {
			jsonRes.put("result", ServerErrorResponse.USER_NOT_LOGGED_IN.toString());
			result = jsonRes.toString();
			return result;
		}
		
		try {
			jsonReq = new JSONObject(dataJSON);
		} catch(JSONException e) {
			jsonRes.put("result", ServerErrorResponse.MALFORMED_REQUEST.toString());
			result = jsonRes.toString();
			return result;
		}
		
		String role = (String)session.getAttribute("role");
		
		/* check if json data was not malformed */
		/* check number of parameters needs to act on filtering. Without clientId and approverId */
		int paramNumberToBeCheck = 0;
		
		if(!(jsonReq.isNull("employeeAccountingPeriodState"))) {
			paramNumberToBeCheck++;
		}
		if(!(jsonReq.isNull("userFirstName"))) {
			paramNumberToBeCheck++;
		}
		if(!(jsonReq.isNull("userLastName"))) {
			paramNumberToBeCheck++;
		}
		if(!(jsonReq.isNull("employeePosition"))) {
			paramNumberToBeCheck++;
		}
		if(!(jsonReq.isNull("businessUnitId"))) {
			paramNumberToBeCheck++;
		}
		if(!(jsonReq.isNull("employeeState"))) {
			paramNumberToBeCheck++;
		}
		if(!(jsonReq.isNull("userAccountState"))) {
			paramNumberToBeCheck++;
		}
		if(!(jsonReq.isNull("userRole"))) {
			paramNumberToBeCheck++;
		}
		if(!(jsonReq.isNull("clientId"))) {
			paramNumberToBeCheck++;
		}
		
		if((paramNumberToBeCheck == 0) && (jsonReq.isNull("clientId")) && (jsonReq.isNull("approverId"))) {
			if(!(role.equals("admin"))) {
				jsonRes.put("result",ServerErrorResponse.MALFORMED_REQUEST.toString());
				result = jsonRes.toString();
				System.out.println(result);
				return result;
			}
		}
			
		/* check  authorization */
		if(!((role.equals("approver")) || (role.equals("clientAdmin")) || (role.equals("admin")))) {
			jsonRes.put("result", ServerErrorResponse.USER_NOT_ENTITLED.toString());
			result = jsonRes.toString();
			System.out.println(result);
			return result;
		}
		
		String approverId = "";
		String clientId = null;
		Integer id_client = null;
		if(role.equals("approver") || role.equals("clientAdmin")) {
			try {
				clientId = jsonReq.getString("clientId");
				approverId = jsonReq.getString("approverId");
				id_client = Integer.parseInt(clientId);
			} catch(JSONException e) {
				jsonRes.put("result",ServerErrorResponse.MALFORMED_REQUEST.toString());
				result = jsonRes.toString();
				return result;
			} catch( NumberFormatException e1) {
				jsonRes.put("result",ServerErrorResponse.MALFORMED_REQUEST.toString());
				result = jsonRes.toString();
				return result;
			}
		}
		
		int sessionUserId = (Integer)session.getAttribute("sessionUserId");
		List<JSONObject> basicUserData = new ArrayList<JSONObject>();
		
		try {
			
			if(role.equals("clientAdmin")) {
				/* check if clientAdmin has privilege to client */
				ClientProfile clientProfile = UserEntitlement.checkClientAdminPrivilegeToClientProfile(sessionUserId, id_client);
				if(clientProfile == null) {
					jsonRes.put("result", ServerErrorResponse.USER_NOT_ENTITLED.toString());
					result = jsonRes.toString();
					return result;
				}
				if(!(jsonReq.isNull("userRole"))) {
					if(!(jsonReq.getString("userRole").equals("employee") || jsonReq.getString("userRole").equals("approver"))) {
						jsonRes.put("result", ServerErrorResponse.USER_NOT_ENTITLED.toString());
						result = jsonRes.toString();
					}
				} 
				if(jsonReq.isNull("approverId")) {
					List<EmployeeProfile> employeeProfiles = EmployeeProfile.getEmployeeProfilesBySpecifiedClientIdFromDB(id_client);
					basicUserData = User.findEmployeesBySpecifiedParams(employeeProfiles, id_client, paramNumberToBeCheck, jsonReq);
					
				} else {
					Approver approver = Approver.getApproverWithEmployeesFromDB("id_user", Integer.parseInt(approverId));
					List<EmployeeProfile> employeeProfiles = Employee.getEmployeeProfiles(approver.getEmployees());
					employeeProfiles.add(approver.getApproverProfile());
					basicUserData = User.findEmployeesBySpecifiedParams(employeeProfiles, id_client, paramNumberToBeCheck, jsonReq);
				}
	
				
			} else if(role.equals("approver")) {
				if( (jsonReq.isNull("approverId")) || (Integer.parseInt(approverId) != sessionUserId)) {
					jsonRes.put("result", ServerErrorResponse.USER_NOT_ENTITLED.toString());
					result = jsonRes.toString();
					return result;
				}
				ClientProfile clientProfile = null;
				clientProfile = UserEntitlement.checkEmployeePrivilegeToClient(role, Integer.parseInt(approverId), id_client);
				if(clientProfile == null) {
					jsonRes.put("result", ServerErrorResponse.USER_NOT_ENTITLED.toString());
					result = jsonRes.toString();
					return result;
				}
				Approver approver = Approver.getApproverWithEmployeesFromDB("id_user", sessionUserId);
				List<EmployeeProfile> employeeProfiles = Employee.getEmployeeProfiles(approver.getEmployees());
				employeeProfiles.add(approver.getApproverProfile());
				basicUserData = User.findEmployeesBySpecifiedParams(employeeProfiles, id_client, paramNumberToBeCheck, jsonReq);
			} else {
				/* admin*/
				if(!(jsonReq.isNull("clientId"))) {
					try {
						clientId = jsonReq.getString("clientId");
						id_client = Integer.parseInt(clientId);
					} catch(JSONException e) {
						jsonRes.put("result",ServerErrorResponse.MALFORMED_REQUEST.toString());
						result = jsonRes.toString();
						return result;
					} catch( NumberFormatException e1) {
						jsonRes.put("result",ServerErrorResponse.MALFORMED_REQUEST.toString());
						result = jsonRes.toString();
						return result;
					}
				}
				
				if(!(jsonReq.isNull("userRole"))) {
					List<User> users;
					if((jsonReq.getString("userRole").equals("clientAdmin")) || (jsonReq.getString("userRole").equals("admin"))) {
						if(jsonReq.getString("userRole").equals("admin")) {
							Role adminRole = Role.getRoleFromDB("admin");
							users = User.getUsersFromDB("role.id", adminRole.getId_role());
						} else {
							Role clientAdminRole = Role.getRoleFromDB("clientAdmin");
							users = User.getUsersFromDB("role.id", clientAdminRole.getId_role());
						}
						basicUserData = User.findUsersBySpecifiedParams(users, paramNumberToBeCheck, jsonReq, basicUserData);
					} else {
						List<EmployeeProfile> employeeProfiles;
						employeeProfiles = EmployeeProfile.getEmployeeProfilesFromDB();
						basicUserData = User.findEmployeesBySpecifiedParams(employeeProfiles, id_client, paramNumberToBeCheck, jsonReq);	
					}
				} else {
					List<EmployeeProfile> employeeProfiles;
					List<User> users;
					List<User> tmp;
					employeeProfiles = EmployeeProfile.getEmployeeProfilesFromDB();
					Role clientAdminRole = Role.getRoleFromDB("clientAdmin");
					users = User.getUsersFromDB("role.id", clientAdminRole.getId_role());
					Role adminRole = Role.getRoleFromDB("admin");
					tmp = User.getUsersFromDB("role.id", adminRole.getId_role());
					for(User user: tmp) {
						users.add(user);
					}
					basicUserData = User.findEmployeesBySpecifiedParams(employeeProfiles, id_client, paramNumberToBeCheck, jsonReq);
					basicUserData = User.findUsersBySpecifiedParams(users,paramNumberToBeCheck,jsonReq,basicUserData);
				}
			}
		}catch(NumberFormatException npe) {
			jsonRes.put("result", ServerErrorResponse.INTERNAL_ERROR.toString());
			result = jsonRes.toString();
			return result;
		}
		
		jsonRes.put("users", basicUserData);
		jsonRes.put("result","OK");
		result = jsonRes.toString();
		return result;
	}
}
